package com.xb.chain.netty.message.handle;

import cn.hutool.core.util.RandomUtil;
import cn.hutool.json.JSONUtil;
import com.xb.chain.constant.InfoConstant;
import com.xb.chain.netty.message.entity.ConnectionMessage;
import com.xb.chain.netty.message.entity.Message;
import com.xb.chain.constant.MessageType;
import com.xb.chain.netty.message.entity.GetChainHeightMessage;
import com.xb.chain.netty.message.entity.SyncNodeMessage;
import com.xb.chain.netty.server.NodeServerStart;
import io.netty.channel.Channel;

import java.util.ArrayList;
import java.util.List;

/**
 *  客户端向服务端发送信息
 */
public class ClientToServerMessage {


    /**
     *  通知各个节点，有新节点加入
     */
    public static void newNodeAdd() {
        InfoConstant.clientChannelGroup.forEach((k, v) -> {
            // 不通知本节点
            if (!(k.getIp().equals(NodeServerStart.blockChainProperties.getServerIp()) && k.getPort().equals(NodeServerStart.blockChainProperties.getPort()))) {
                Message<ConnectionMessage> message = Message.createMessage(MessageType.NEW_CONNECTION, ConnectionMessage.builder().ip(NodeServerStart.blockChainProperties.getServerIp()).port(NodeServerStart.blockChainProperties.getPort()).build());
                noticeServerNode(v, message);
            }
        });
    }

    /**
     * 随机抽取节点进行同步
     */
    public static void initSyncNode() {
        List<Channel> list = new ArrayList<>();
        InfoConstant.clientChannelGroup.forEach((k, v) -> {
            // 不通知本节点
            if (!(k.getIp().equals(NodeServerStart.blockChainProperties.getServerIp()) && k.getPort().equals(NodeServerStart.blockChainProperties.getPort()))) {
                list.add(v);
            }
        });
        if (list.size() > 0) {
            Channel channel = list.get(RandomUtil.randomInt(list.size()));
            SyncNodeMessage syncNodeMessage = SyncNodeMessage.builder().ip(NodeServerStart.blockChainProperties.getServerIp()).port(NodeServerStart.blockChainProperties.getPort()).build();
            Message<SyncNodeMessage> message = Message.createMessage(MessageType.SYNC_BLOCK_INFO, syncNodeMessage);
            noticeServerNode(channel,message);
        }

    }

    /**
     *  向所有节点发送同步节点信息（不包括自己）
     */
    public static void syncNodeHeightAll(){
        InfoConstant.clientChannelGroup.forEach((k, v) -> {
            // 不通知本节点
            if (!(k.getIp().equals(NodeServerStart.blockChainProperties.getServerIp()) && k.getPort().equals(NodeServerStart.blockChainProperties.getPort()))) {

                GetChainHeightMessage syncNodeMessage = GetChainHeightMessage.builder().ip(NodeServerStart.blockChainProperties.getServerIp()).port(NodeServerStart.blockChainProperties.getPort()).build();
                Message<GetChainHeightMessage> message = Message.createMessage(MessageType.GET_CHAIN_HEIGHT, syncNodeMessage);
                noticeServerNode(v,message);
            }
        });
    }

    /**
     *  向指定节点发送消息
     */
    public static void basisIpAndPortSendMessage(String ip,Integer port,Message message){
        Channel channel = InfoConstant.getClientChannel(ip, port);
        noticeServerNode(channel,message);
    }


    // 通过channel通知有新节点加入
    private static void noticeServerNode(Channel channel, Message message) {
        channel.writeAndFlush(JSONUtil.toJsonStr(message) + "\r\n");
    }


}
